package com.bitmart.biometric

import android.os.*
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import com.biometric.core.AuthClient
import com.biometric.core.authenticator.AuthenticateListenerAdapter
import com.biometric.core.authenticator.impl.CredentialAuthenticator
import com.biometric.core.authenticator.impl.FaceAuthenticator
import com.biometric.core.authenticator.impl.FingerprintAuthenticator
import com.biometric.core.checker.FaceCapableChecker
import com.biometric.core.fallback.FallbackStrategy.Companion.MeetMaxAttempt
import com.biometric.core.retriever.DefaultBiometricMetaDataRetriever
import com.biometric.core.support.FaceAuthCallableRule
import com.biometric.core.support.FaceSupportManager
import com.blankj.utilcode.util.ToastUtils
import com.wei.android.lib.fingerprintidentify.Authenticator
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private val TAG = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        bindClick()
    }

    private fun bindClick() {
        //指纹解锁，系统PIN/Pattern兜底
        fingerprint_pin_fallback_case.setOnClickListener { fallBackCase() }

        // 单独指纹解锁，自定义UI
        fingerprint_custom_ui_no_fallback_case.setOnClickListener {
            customFingerprintUiCase()
        }

        //单独指纹
        fingerprint_only_case.setOnClickListener { fingerprintOnlyCase() }

        //单独人脸
        face_only_case.setOnClickListener { faceOnlyCase() }

        //指纹解锁，锁定后使用系统密码解锁
        fingerprint_lockout_system_fallback_case.setOnClickListener {
            fingerprintLockoutCredentialFallbackCase()
        }
        //自定义手势UI解锁
        customOnly.setOnClickListener {
            customUiCase()
        }

        systemCredentialCase.setOnClickListener {
            systemCredentialCase()
        }
        replaceFaceRule.setOnClickListener {
            replaceRuleCase()
        }
    }

    private lateinit var dialog: AlertDialog
    private fun customFingerprintUiCase() {
        val metaDataRetriever = DefaultBiometricMetaDataRetriever
        fingerprint_custom_ui_no_fallback_case.isEnabled =
            metaDataRetriever.isFingerprintAuthenticationEnabled()
        if (metaDataRetriever.isFingerprintHardwareEnabled().not()) {
            fingerprint_custom_ui_no_fallback_case.text = "没有指纹识别器"
            return
        }
        if (metaDataRetriever.isFingerprintAuthenticationEnabled().not()) {
            fingerprint_custom_ui_no_fallback_case.text = "没有录入指纹数据"
            return
        }

        val client = AuthClient.Builder(this)
            .authenticator(FingerprintAuthenticator())
            .listener(object : AuthenticateListenerAdapter() {

                override fun onFailed() {
                    super.onFailed()
                }

                override fun onError(code: Int, errMsg: CharSequence) {
                    super.onError(code, errMsg)
                    ToastUtils.showShort("code:$code $errMsg")
                    dialog.dismiss()
                }

                override fun onSuccess() {
                    super.onSuccess()
                    dialog.dismiss()
                    ToastUtils.showShort("unlock success!")
                }
            })
            .build()

        dialog = AlertDialog.Builder(this)
            .setTitle("Custom Fingerprint Unlock Ui")
            .setMessage("I am custom Fingerprint unlock Ui")
            .setNegativeButton("cancel me") { dialog, which ->
                dialog.dismiss()
            }.show()
        client.startAuthenticate()
    }

    private fun fingerprintLockoutCredentialFallbackCase() {
        val client = AuthClient.Builder(this)
            .authenticator(FingerprintAuthenticator())
            .maxAttemptPerAuthenticator(2)
            .credentialAuthenticateWhileBiometricLockout("hello")
            .listener(object : AuthenticateListenerAdapter() {
                override fun onError(code: Int, errMsg: CharSequence) {
                    super.onError(code, errMsg)
                    ToastUtils.showShort(errMsg)
                }

                override fun onFailed() {
                    super.onFailed()
                    ToastUtils.showShort("指纹不匹配")
                }
            })
            .build()
        client.startAuthenticate()
    }

    private fun fingerprintOnlyCase() {
        fingerprint_only_case.isEnabled =
            DefaultBiometricMetaDataRetriever.isFingerprintAuthenticationEnabled()

        if (DefaultBiometricMetaDataRetriever.isFingerprintAuthenticationEnabled().not()) {
            return
        }
        if (DefaultBiometricMetaDataRetriever.isFingerprintAuthenticationEnabled().not()) {
            fingerprint_only_case.text = "只使用指纹解锁（不可用）"
            return
        }
        val authenticateListener = object :
            Authenticator.AuthenticateListener {
            override fun onSuccess() {
                ToastUtils.showShort("success😁")
            }

            override fun onFailed() {
                ToastUtils.showShort("onFailed😁")
            }

            override fun onError(code: Int, errMsg: CharSequence) {
                ToastUtils.showShort("onError😁$code")
            }

            override fun onCancelled() {
                ToastUtils.showShort("onCancelled😁")
            }

        }

        val authenticator = FingerprintAuthenticator()
        val client = AuthClient.Builder(this)
            .credentialAuthenticateWhileBiometricLockout(
                title = "you fail too may times,please unlock with credential until you can use biometric authentication"
            )
            .authenticator(authenticator)
            .listener(authenticateListener)
            .maxAttemptPerAuthenticator(5)
            .setReachMaxAttemptCallback(object : AuthClient.ReachMaxAttemptCallback {
                override fun onReach(authenticator: Authenticator) {
                    Log.i(TAG, "onReach: ==========")
                    ToastUtils.showShort("尝试多次指纹，滚粗~😭")
                    authenticator.cancelAuthenticate()
                }
            })
            .build()

        ToastUtils.showShort(
            "${
                BiometricManager.from(this)
                    .canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK)
            }"
        )
        client.startAuthenticate()
    }

    private fun faceOnlyCase() {
        val isFaceEnabled = DefaultBiometricMetaDataRetriever.isFaceAuthenticationEnabled()
        if (isFaceEnabled.not()) {
            face_only_case.text = "只使用人脸解锁(不可用)"
            face_only_case.isEnabled = false
            return
        }
        val listener = object : Authenticator.AuthenticateListener {
            override fun onSuccess() {
                Toast.makeText(applicationContext, "success😁", Toast.LENGTH_SHORT).show()
            }

            override fun onFailed() {
                Toast.makeText(applicationContext, "fail笑", Toast.LENGTH_SHORT).show()
            }

            override fun onError(code: Int, errMsg: CharSequence) {
                Toast.makeText(applicationContext, "error😁", Toast.LENGTH_SHORT).show()
            }

            override fun onCancelled() {
                Toast.makeText(applicationContext, "cancel😁", Toast.LENGTH_SHORT).show()
            }

        }
        val faceAuthenticator = FaceAuthenticator.get(this, "face unlock", "cancel unlock")
        val client = AuthClient.Builder(this)
            .credentialAuthenticateWhileBiometricLockout(
                title = "you fail too may times,please unlock with credential until you can use biometric authentication"
            )
            .authenticator(faceAuthenticator)
            .listener(listener)
            .maxAttemptPerAuthenticator(2)
            .setReachMaxAttemptCallback(object : AuthClient.ReachMaxAttemptCallback {
                override fun onReach(authenticator: Authenticator) {
                    Log.i(TAG, "onReach: ==========")
                    ToastUtils.showShort("尝试多次，😭")
                    authenticator.cancelAuthenticate()
                }
            })
            .build()
        client.startAuthenticate()
    }

    var customUiAuthClient: AuthClient? = null
    private fun customUiCase() {
        if (customUiAuthClient == null) {
            val listener = object : Authenticator.AuthenticateListener {
                override fun onSuccess() {
                    ToastUtils.showShort("success😁")
                }

                override fun onFailed() {
                    ToastUtils.showShort("fail😠")
                }

                override fun onError(code: Int, errMsg: CharSequence) {
                    ToastUtils.showShort("error😭")
                }

                override fun onCancelled() {
                    ToastUtils.showShort("cancel🥶")
                }

            }
            val gestureLockAuthenticator =
                GestureLockViewAuthenticatorFragment(this)
            customUiAuthClient = AuthClient.Builder(this)
                .authenticator(gestureLockAuthenticator)
                .listener(listener)
                .maxAttemptPerAuthenticator(5)
                .setReachMaxAttemptCallback(object : AuthClient.ReachMaxAttemptCallback {
                    override fun onReach(authenticator: Authenticator) {
                        Log.i(TAG, "onReach: ==========")
                        ToastUtils.showShort("尝试多次，😭")
                        authenticator.cancelAuthenticate()

                        CredentialAuthenticator(this@MainActivity, "hello")
                            .authenticate(listener)
                    }
                })
                .build()
        }
        customUiAuthClient?.startAuthenticate()
    }

    private fun fallBackCase() {
        val authenticateListener = object :
            Authenticator.AuthenticateListener {
            override fun onSuccess() {
                ToastUtils.showShort("success😁")
            }

            override fun onFailed() {
                ToastUtils.showShort("onFailed😁")
            }

            override fun onError(code: Int, errMsg: CharSequence) {
                Log.i(TAG, "onError: =========ERRRRRRRRRRRROOOOORR")
                ToastUtils.showShort("onError😁$code")
            }

            override fun onCancelled() {
                ToastUtils.showShort("onCancelled😁")
            }

        }

        val authenticator = FingerprintAuthenticator()
        val client = AuthClient.Builder(this)
            .credentialAuthenticateWhileBiometricLockout(
                title = "you fail too may times,please unlock with credential until you can use biometric authentication"
            )
            .authenticator(authenticator)
            .fallback(CredentialAuthenticator(this, "先使用Pattern解锁"))
            .fallbackStrategy(MeetMaxAttempt)
            .listener(authenticateListener)
            .maxAttemptPerAuthenticator(5)
            .setReachMaxAttemptCallback(object : AuthClient.ReachMaxAttemptCallback {
                override fun onReach(authenticator: Authenticator) {
                    Log.i(TAG, "onReach: ==========")
                    ToastUtils.showShort("尝试多次，😭")
                    authenticator.cancelAuthenticate()

                    AuthClient.Builder(this@MainActivity)
                        .listener(AuthenticateListenerAdapter())
                        .authenticator(CredentialAuthenticator(this@MainActivity, "hello"))
                        .build()
                        .startAuthenticate()
                }
            })
            .build()

        ToastUtils.showShort(
            "${
                BiometricManager.from(this)
                    .canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK)
            }"
        )
        client.startAuthenticate()
    }

    private fun systemCredentialCase(){
        AuthClient.Builder(this)
            .authenticator(CredentialAuthenticator(this,"系统密码解锁"))
            .build()
            .startAuthenticate()
    }

    private fun replaceRuleCase() {
        //模拟默认的人脸调用检验,所有手机都可以调用人脸能力——
        //导致的结果是会调用指纹解锁，暂时只是测试规则。目前已经通过三星手机的测试）
        val newRule = object : FaceAuthCallableRule {
            override fun isCallable(): Boolean {
                return true
            }

        }
        val faceChecker = object : FaceCapableChecker {
            override fun check(): Boolean {
                return true
            }

        }
        FaceSupportManager.registerChecker(faceChecker)
        DefaultBiometricMetaDataRetriever.updateFaceRule(newRule)

        AuthClient.Builder(this)
            .authenticator(FaceAuthenticator.get(this, "face unlock", "cancel unlock"))
            .build()
            .startAuthenticate()
    }

    override fun onResume() {
        super.onResume()
        setBiometricInfo()
    }

    private fun setBiometricInfo() {
        val biometricRetriever = DefaultBiometricMetaDataRetriever
        val stringBuffer = StringBuffer()
        stringBuffer.append("manufacture:" + Build.MANUFACTURER + "\nmodel:" + Build.MODEL + "\nbrand:" + Build.BRAND + "\nboard:" + Build.BOARD)
        stringBuffer.append("\n")
        stringBuffer.append("支持生物特征识别：${biometricRetriever.canBiometricAuthenticate()}")
        stringBuffer.append("\n")
        stringBuffer.append("指纹是否支持：${biometricRetriever.isFingerprintHardwareEnabled()}")
        stringBuffer.append("\n")
        stringBuffer.append("指纹是否录入：${biometricRetriever.isFingerprintAuthenticationEnabled()}")
        stringBuffer.append("\n")
        stringBuffer.append("人脸是否可以调用：${biometricRetriever.isFaceAuthenticationEnabled()}")
        biometric_display.text = stringBuffer.toString()
    }
}